#include <stdio.h>
#include <winsock2.h>
#include <string.h>

#pragma comment(lib, "ws2_32.lib") // Winsock Library

#define PORT 60000
#define BROADCAST_ADDR "255.255.255.255"
#define BUFFER_SIZE 1024
/*************************
 * 
 * //    gcc test.c -o test.exe  -lws2_32 -liphlpapi
 * 
*/

int main() {
    WSADATA wsa;
    SOCKET s;
    struct sockaddr_in server, client;
    int c;
    char message[BUFFER_SIZE];
    char server_reply[BUFFER_SIZE];
    int recv_size;
    int send_len, recv_len, send_time = 0, i;

    // Initialize Winsock
    printf("Initializing Winsock...");
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
        printf("Failed. Error Code : %d", WSAGetLastError());
        return 1;
    }
    printf("Initialized.\n");

    // Create a socket
    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
        printf("Could not create socket : %d", WSAGetLastError());
    }
    printf("Socket created.\n");

    // Set up the server address structure
    server.sin_family = AF_INET;
    server.sin_port = htons(PORT);
    server.sin_addr.s_addr = INADDR_ANY;

    // Bind the socket to the specified port
    if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
        printf("Bind failed with error code : %d", WSAGetLastError());
    }
    printf("Bind done.\n");

    // // Enable broadcasting on the socket
    // int broadcast = 1;
    // if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)) == SOCKET_ERROR) {
    //     printf("setsockopt() failed with error code : %d", WSAGetLastError());
    // }
    // printf("Broadcast enabled.\n");

    // // Prepare the broadcast message
    strcpy(message, "Hello, world! This is a device send message.");
    send_len = strlen(message);
    // // Send the broadcast message
    // struct sockaddr_in broadcast_addr;
    // broadcast_addr.sin_family = AF_INET;
    // broadcast_addr.sin_port = htons(PORT);
    // broadcast_addr.sin_addr.s_addr = inet_addr(BROADCAST_ADDR);

    // if (sendto(s, message, strlen(message), 0, (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr)) == SOCKET_ERROR) {
    //     printf("sendto() failed with error code : %d", WSAGetLastError());
    // }
    // printf("Broadcast message sent.\n");

    // Receive responses from other hosts
    while (1) {
        c = sizeof(client);
        if ((recv_size = recvfrom(s, server_reply, BUFFER_SIZE, 0, (struct sockaddr *)&client, &c)) == SOCKET_ERROR) {
            printf("recvfrom() failed with error code : %d", WSAGetLastError());
            break;
        }
        for(i = 0; i < recv_size/16; i++){
             printf("[index:%d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", i, server_reply[0 + i*16], server_reply[1 + i*16], server_reply[2 + i*16],\
                     server_reply[3 + i*16], server_reply[4 + i*16], server_reply[5 + i*16],server_reply[6 + i*16], server_reply[7 + i*16], server_reply[8 + i*16],server_reply[9 + i*16], server_reply[10 + i*16], server_reply[11 + i*16], \
                     server_reply[12 + i*16], server_reply[13 + i*16], server_reply[14 + i*16], server_reply[15 + i*16]);

        }
        printf("[index:%d] \t", i);
        for(i = 0; i < recv_size%16; i++){
                printf("%02x \t", server_reply[i + (recv_size/16)*16]);
        }
        printf(" \n");

        server_reply[recv_size] = '\0'; // Null-terminate the received message
        printf("Received reply from %s:%d - %s\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port), server_reply);
        send_time ++;
        message[send_len] = '0' + send_time%9;
       int send_len = sendto(s, message, strlen(message), 0, (struct sockaddr *)&client, c);
        if (send_len < 0) {
            perror("sendto");
            exit(EXIT_FAILURE);
        }
    
    }

    // Close the socket
    closesocket(s);
    WSACleanup();

    return 0;
}